<?php

class Person
{
    var $name;

    /**
     * @return mixed
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param mixed $name
     */
    public function setName($name): void
    {
        $this->name = $name;
    }

}

class User123
{
    var $name;
    var $age;
    var $password;

    var $person;

    /**
     * @return mixed
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param mixed $name
     */
    public function setName(string $name): void
    {
        $this->name = $name;
    }

    /**
     * @return mixed
     */
    public function getPassword()
    {
        return $this->password;
    }

    /**
     * @param mixed $password
     */
    public function setPassword(string $password): void
    {
        $this->password = $password;
    }

    /**
     * @return mixed
     */
    public function getAge()
    {
        return $this->age;
    }

    /**
     * @param mixed $age
     */
    public function setAge(int $age): void
    {
        $this->age = $age;
    }

    /**
     * @return mixed
     */
    public function getPerson()
    {
        return $this->person;
    }

    /**
     * @param mixed $person
     */
    public function setPerson(Person $person): void
    {
        $this->person = $person;
    }


}

/*$user123 = new User123();
$user123->setName("我是爸爸");
//echo $user123->getName();
echo $user123->getAge();*/

$data = [
    "age" => 1,
    "name" => "我是爸爸",
    "password" => "我是123",
    "person" => [
        [
            "name" => 1,
        ],
        [
            "name" => 2,
        ]
    ]
];

function firstLetter(){

}
function getSetMethod($classMethods,$key){
    $setPersonMethod = null;
    foreach ($classMethods as $item) {
        $key = ucfirst($key);
        if ($item->name == "set$key") {
            $setPersonMethod = $item;
        };
    }
    return $setPersonMethod;
}
function getFirstParamClassName($method){
    $setParam = $method->getParameters()[0];
    $setParamClass = $setParam->getClass();
    return $setParamClass->name;
}
// 使用反射 实例化对象
function makeObject($clazz, $data)
{
    $ref = new ReflectionClass($clazz);
    $proppertiesArray = $ref->getProperties();
    $classMethods = $ref->getMethods();
    $newObject = $ref->newInstance();
    foreach ($proppertiesArray as $item) {
        //对象属性name
        $propertykey = $item->name;
        if(/*是array 嵌套*/is_array($data[$propertykey])){
/*
 * 1 获取 set[属性的名称]方法
 * 2 获取这个方法的第一个参数的类型
 * 3 如果是 class 直接递归
 * 4 得到这个参数的实例 setvalue
*/
            $setMethod = getSetMethod($classMethods, $propertykey);
            $setMethodFirstParamsClassName = getFirstParamClassName($setMethod);
            $valueObj=makeObject($setMethodFirstParamsClassName, $data[$propertykey]);
            $item->setValue($newObject, $valueObj);
        }else{
            $item->setValue($newObject, $data[$propertykey]);
        }


    }
    return $newObject;
}

var_dump(makeObject(User123::class, $data));;